package peace.gui.controls {
import flash.events.EventDispatcher;

[Event(name="change", type="peace.gui.controls.SelectEvent")]
/**
 * Менеджер группы контролов
 */
public class GroupSelection extends EventDispatcher {
    public var allowMultipleSelection:Boolean;
    /**
     * специальный флажок для поведения радиокнопок:
     * <ul>
     * <li> не работает флаг allowMultipleSelection (всегда allowMultipleSelection = false)
     * <li> при попытке снять выделение с кнопки возвращаем его обратно
     * </ul>
     */
    public var allowRadioMode:Boolean = false;
    protected var _controls:Array = [];
    protected var selected:Array = [];

    /**
     * @param buttons массив Control
     * @param allowMultipleSelection доступность выделять несколько
     * @param startSelection Control или массив Control
     */
    public function GroupSelection(controls:Array = null, allowMultipleSelection:Boolean = false, allowRadioMode:Boolean = false, startSelection:* = null) {
        this.allowMultipleSelection = allowMultipleSelection;
        this.allowRadioMode = allowRadioMode;

        if (controls) {
            this.controls = controls;
        }

        if (startSelection) {
            this.selection = startSelection;
        }
    }

    public function add(c:Control):void {
        if (_controls.indexOf(c) > -1) {
            return;
        }

        _controls.push(c);

        if (c.selected) {
            if (allowRadioMode || allowMultipleSelection) {
                clearSelection(false);
            }
            addToSelection(c);
        }

        c.addEventListener(SelectEvent.CHANGE, onChangeSelectionEvent, false, 0, true);
    }

    public function remove(c:Control):void {
        var index:int = _controls.indexOf(c);
        if (index > -1) {
            _controls.splice(index, 1);
            c.removeEventListener(SelectEvent.CHANGE, onChangeSelectionEvent);
        }

        removeFromSelection(c);
    }

    public function removeAll():void {
        // трем существующее выделение
        clearSelection(false);

        var c:Control;
        for each (c in _controls) {
            c.removeEventListener(SelectEvent.CHANGE, onChangeSelectionEvent);
        }

        _controls.length = 0;
    }

    public function select(c:Control):void {
        c.selected = true;
        addToSelection(c);
    }

    public function blur(c:Control):void {
        c.selected = false;
        removeFromSelection(c);
    }

    /**
     * @param items Control или массив Control
     */
    public function set selection(items:*):void {
        clearSelection(false);

        if (items is Array) {
            selected = items;
        }
        else if (items is Control) {
            selected.push(items);
        }

        var c:Control;
        for each (c in selected) {
            c.selected = true;
        }

        dispatchEvent(new SelectEvent(SelectEvent.CHANGE, selected));
    }

    /**
     * @return массив Control или Control
     */
    public function get selection():* {
        if (selected.length == 0) return null;
        return selected.length == 1 ? selected[0] : selected;
    }

    /**
     * Чистим все выделение в группе
     * @param needDispatchEvent
     */
    public function clearSelection(needDispatchEvent:Boolean = true):void {
        if (selected.length == 0) needDispatchEvent = false;

        var c:Control;
        for each (c in selected) {
            c.selected = false;
        }
        selected.length = 0;

        if (needDispatchEvent) {
            dispatchEvent(new SelectEvent(SelectEvent.CHANGE, null));
        }
    }

    public function set controls(array:Array):void {
        removeAll();

        var i:int;
        for (i = 0; i < array.length; i++) {
            add(Control(array[i]));
        }

    }

    /**
     * @return массив контролов группы
     */
    public function get controls():Array {
        return _controls;
    }

    private function onChangeSelectionEvent(e:SelectEvent):void {
        var c:Control = Control(e.selection);
        var toSend:* = null;
        if (allowMultipleSelection && !allowRadioMode) {
            if (c.selected) {
                addToSelection(c);
            }
            else {
                removeFromSelection(c);
            }
            toSend = selected;
        }
        else {
            if (c != selected[0]) {
                if (selected.length > 0) {
                    Control(selected[0]).selected = false;
                    removeFromSelection(Control(selected[0]));
                }
                addToSelection(c);
                toSend = c;
            }
            else if (allowRadioMode) {
                c.selected = true;
                return;
            }
            // если сняли выделение с кнопки
            else {
                removeFromSelection(c);
                toSend = null;
            }
        }

        dispatchEvent(new SelectEvent(SelectEvent.CHANGE, toSend));
    }

    protected function addToSelection(c:Control):void {
        if (selected.indexOf(c) > -1) return;

        selected.push(c);
    }

    protected function removeFromSelection(c:Control):void {
        var index:int = selected.indexOf(c);
        if (index == -1) return;

        selected.splice(index, 1);
    }
}
}